package cn.mrlong.base.utils

import android.content.ContentResolver
import android.content.Context
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.net.Uri
import android.os.Environment
import android.provider.MediaStore
import cn.mrlong.base.extensions.isBlank
import java.io.File
import java.io.FileInputStream
import java.io.FileOutputStream
import java.io.IOException
import java.text.DecimalFormat
import java.util.*

/**
 * 作者：BINGO
 * 时间：2021/04/21 14:47
 */
/**
 * Created by ly343 on 2018/7/6.
 */
object FileUtils {
    /**
     * 获取文件夹下的所有文件
     *
     * @param imagePath
     * @return
     */
    fun getFilePathList(imagePath: String): List<String> {
        val filesPath: MutableList<String> = ArrayList()
        val mfile = File(imagePath)
        val files = mfile.listFiles()
        if (files != null && files.size > 0) {
            for (i in files.indices) {
                if (!files[i].isDirectory) // 判断是否为文件夹
                {
                    val file = files[i]
                    val s = getSuffixName(file.name)
                    val b = checkIsImageFile(file.path)
                    if (b && s == "mp4") {
                        filesPath.add(file.path)
                    }
                } else {
                    val file = files[i]
                    getFilePathList(imagePath + File.separator + file.name)
                }
            }
        }
        return filesPath
    }

    //获取文件名
    fun getFileNameWithoutSuffix(fileName: String): String {
        var fileN = fileName.substring(0, fileName.lastIndexOf("."))
        fileN = fileN.replace("_".toRegex(), "")
        return fileN
    }

    private fun checkIsImageFile(fName: String): Boolean {
        var isImageFile = false

        // 获取扩展名
        val FileEnd = fName.substring(fName.lastIndexOf(".") + 1, fName.length).toLowerCase()
        isImageFile =
            FileEnd == "jpg" || FileEnd == "gif" || FileEnd == "png" || FileEnd == "jpeg" || FileEnd == "bmp" || FileEnd == "mp4"
        return isImageFile
    }

    //uri转url
    fun getRealFilePath(context: Context, uri: Uri?): String? {
        if (null == uri) return null
        val scheme = uri.scheme
        var data: String? = null
        if (scheme == null) data = uri.path else if (ContentResolver.SCHEME_FILE == scheme) {
            data = uri.path
        } else if (ContentResolver.SCHEME_CONTENT == scheme) {
            val cursor = context.contentResolver.query(
                uri,
                arrayOf(MediaStore.Images.ImageColumns.DATA),
                null,
                null,
                null
            )
            if (null != cursor) {
                if (cursor.moveToFirst()) {
                    val index = cursor.getColumnIndex(MediaStore.Images.ImageColumns.DATA)
                    if (index > -1) {
                        data = cursor.getString(index)
                    }
                }
                cursor.close()
            }
        }
        return data
    }

    /**
     * 删除指定目录下文件及目录
     *
     * @param deleteThisPath
     * @return
     */
    fun deleteFolderFile(filePath: String?, deleteThisPath: Boolean) {
        if (!String.isBlank(filePath)) {
            try {
                val file = File(filePath)
                if (file.isDirectory) { // 如果下面还有文件
                    val files = file.listFiles()
                    for (i in files.indices) {
                        deleteFolderFile(files[i].absolutePath, true)
                    }
                }
                if (deleteThisPath) {
                    if (!file.isDirectory) { // 如果是文件，删除
                        file.delete()
                    } else { // 目录
                        if (file.listFiles().size == 0) { // 目录下没有文件或者目录，删除
                            file.delete()
                        }
                    }
                }
            } catch (e: Exception) {
                e.printStackTrace()
            }
        }
    }

    /**
     * * 删除方法 这里只会删除某个文件夹下的文件，如果传入的directory是个文件，将不做处理 * *
     *
     * @param directory
     */
    private fun deleteFilesByDirectory(directory: File?): Boolean {
        var clean = false
        try {
            if (directory != null && directory.exists() && directory.isDirectory) {
                for (item in directory.listFiles()) {
                    val b = item.delete()
                    clean = b
                }
            }
        } catch (e: Exception) {
            clean = false
        } finally {
            return clean
        }
    }

    /**
     * 获取当前的存储目录
     * 如果有外部存储卡则先存储到存储卡的zzz；否则存储到当前应用的files下面
     */
    fun getDiskFileDir(context: Context, uniqueName: String): File? {
        val filePath: String
        if (Environment.MEDIA_MOUNTED == Environment.getExternalStorageState() || !Environment.isExternalStorageRemovable()) {
            filePath = Environment.getExternalStorageDirectory().path
            makeRootDirectory(filePath)
        } else {
            filePath = context.filesDir.path
            makeRootDirectory(filePath)
        }
        var file: File? = null
        try {
            file = File(filePath + File.separator + uniqueName)
            if (!file.exists()) {
                file.mkdir()
            }
        } catch (e: Exception) {
            e.printStackTrace()
        }
        return file
    }

    fun makeRootDirectory(filePath: String?) {
        var file: File? = null
        try {
            file = File(filePath)
            if (!file.exists()) {
                file.mkdir()
            }
        } catch (e: Exception) {
        }
    }

    /**
     * 压缩文件方法
     *
     * @param filePath     原路径
     * @param inSampleSize 压缩比例
     * @return 返回新的文件对象（存储在原路径）
     */
    fun compress(filePath: String?, inSampleSize: Int): File? {

        //判断是否大于2MB，小于直接返回
        val sourceFile = File(filePath)
        if (sourceFile.length() < 1024 * 1024 * 2) {
            return sourceFile
        }
        val options = BitmapFactory.Options()
        options.inJustDecodeBounds = true //只加载图像框架
        BitmapFactory.decodeFile(filePath, options)
        // 计算该图像压缩比例，可以调整这个值
        options.inSampleSize = inSampleSize
        //设置加载全部图像内容
        options.inJustDecodeBounds = false
        val bitmap = BitmapFactory.decodeFile(filePath, options)
        return saveBitmap(filePath, bitmap)
    }

    /**
     * 存储文件
     *
     * @param path    原路径
     * @param mBitmap 数据源
     * @return
     */
    fun saveBitmap(path: String?, mBitmap: Bitmap): File? {
        var filePic: File? = null
        var fos: FileOutputStream? = null
        return try {
            filePic = File(path)
            if (!filePic.exists()) {
                filePic.parentFile.mkdirs()
                filePic.createNewFile()
            } else {
                filePic.delete()
            }
            fos = FileOutputStream(filePic)
            mBitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos)
            filePic
        } catch (e: IOException) {
            e.printStackTrace()
            null
        } finally {
            if (null != fos) {
                try {
                    fos.flush()
                    fos.close()
                } catch (e: Exception) {
                    e.printStackTrace()
                }
            }
        }
    }

    /**
     * 获取后缀名
     *
     * @param fileName
     * @return
     */
    fun getSuffixName(fileName: String): String {
        return if (String.isBlank(fileName)) {
            ""
        } else fileName.substring(fileName.lastIndexOf(".") + 1)
    }

    public const val SIZETYPE_B = 1 //获取文件大小单位为B的double值
    public const val SIZETYPE_KB = 2 //获取文件大小单位为KB的double值
    public const val SIZETYPE_MB = 3 //获取文件大小单位为MB的double值
    public const val SIZETYPE_GB = 4 //获取文件大小单位为GB的double值

    /**
     * 获取文件指定文件的指定单位的大小
     *
     * @param filePath 文件路径
     * @param sizeType 获取大小的类型1为B、2为KB、3为MB、4为GB
     * @return double值的大小
     */
    fun getFileOrFilesSize(filePath: String?, sizeType: Int): Double {
        val file = File(filePath)
        var blockSize: Long = 0
        try {
            blockSize = if (file.isDirectory) {
                getFileSizes(file)
            } else {
                getFileSize(file)
            }
        } catch (e: Exception) {
            e.printStackTrace()
        }
        return FormetFileSize(blockSize, sizeType)
    }

    /**
     * 调用此方法自动计算指定文件或指定文件夹的大小
     *
     * @param filePath 文件路径
     * @return 计算好的带B、KB、MB、GB的字符串
     */
    fun getAutoFileOrFilesSize(filePath: String?, sizeType: Int): Double {
        val file = File(filePath)
        var blockSize: Long = 0
        try {
            blockSize = if (file.isDirectory) {
                getFileSizes(file)
            } else {
                getFileSize(file)
            }
        } catch (e: Exception) {
            e.printStackTrace()
        }
        return FormetFileSize(blockSize, sizeType)
    }

    /**
     * 获取指定文件大小
     *
     * @param file
     * @return
     * @throws Exception
     */
    @Throws(Exception::class)
    fun getFileSize(file: File): Long {
        var size: Long = 0
        if (file.exists()) {
            var fis: FileInputStream? = null
            fis = FileInputStream(file)
            size = fis.available().toLong()
        } else {
            file.createNewFile()
        }
        return size
    }

    /**
     * 获取指定文件夹
     *
     * @param f
     * @return
     * @throws Exception
     */
    @Throws(Exception::class)
    fun getFileSizes(f: File): Long {
        var size: Long = 0
        val flist = f.listFiles()
        for (i in flist.indices) {
            size = if (flist[i].isDirectory) {
                size + getFileSizes(flist[i])
            } else {
                size + getFileSize(flist[i])
            }
        }
        return size
    }

    /**
     * 转换文件大小
     *
     * @param fileS
     * @return
     */
    fun formatFileSize(fileS: Long): String {
        val df = DecimalFormat("#.00")
        var fileSizeString = ""
        val wrongSize = "0B"
        if (fileS == 0L) {
            return wrongSize
        }
        fileSizeString = if (fileS < 1024) {
            df.format(fileS.toDouble()) + "B"
        } else if (fileS < 1048576) {
            df.format(fileS.toDouble() / 1024) + "KB"
        } else if (fileS < 1073741824) {
            df.format(fileS.toDouble() / 1048576) + "MB"
        } else {
            df.format(fileS.toDouble() / 1073741824) + "GB"
        }
        return fileSizeString
    }

    /**
     * 转换文件大小,指定转换的类型
     *
     * @param fileS
     * @param sizeType
     * @return
     */
    fun FormetFileSize(fileS: Long, sizeType: Int): Double {
        val df = DecimalFormat("#.00")
        var fileSizeLong = 0.0
        when (sizeType) {
            SIZETYPE_B -> fileSizeLong = java.lang.Double.valueOf(
                df.format(
                    fileS.toDouble()
                )
            )
            SIZETYPE_KB -> fileSizeLong = java.lang.Double.valueOf(
                df.format(
                    fileS.toDouble() / 1024
                )
            )
            SIZETYPE_MB -> fileSizeLong = java.lang.Double.valueOf(
                df.format(
                    fileS.toDouble() / 1048576
                )
            )
            SIZETYPE_GB -> fileSizeLong = java.lang.Double.valueOf(
                df.format(
                    fileS.toDouble() / 1073741824
                )
            )
            else -> {
            }
        }
        return fileSizeLong
    }
}